package com.yang.util;

public class SnowFlake{
    private static final long startTime = 1597889429000L;
    //业务线ID
    private long businessType;
    //机器ID
    private long workId;
    //序列号id
    private static long serialNum=0;

    //regio 得到位移长度
    private static final long serialNumBits = 10L;
    private static final long workIdBits = 7L;
    private static final long businessTypeBits = 5L;

    //得到位移长度
    private static final long workIdShift = serialNumBits;
    private static final long businessTypeShift = workIdShift + workIdBits;
    private static final long timestampShift = businessTypeShift + businessTypeBits;

    //上次请求时间
    private static long lastTimeStamp = 0L;

    //序列号最大值
    private static final long serialNumMax = -1^(-1L<<serialNumBits);

    public SnowFlake(long businessType,long workId) {
        this.businessType = businessType;
        this.workId = workId;
    }

    public long getId(){
        return productionId(businessType,workId);
    }

    /**
     *
     * @param businessType
     * @param workId
     * @return
     */
    public static synchronized long productionId(long businessType,long workId) {
        long timestamp = System.currentTimeMillis();

        if(timestamp == lastTimeStamp) {
            //实现序列号逻辑，序列号
            serialNum = (serialNum+1)&serialNumMax;
            if(serialNum == 0) {
                timestamp = waitNextMillis(timestamp);
            }
        }else {
            serialNum = timestamp&1;
        }
        lastTimeStamp = timestamp;
        return ((timestamp-startTime)<<timestampShift)
                | (businessType<<businessTypeShift)
                | (workId<<workIdShift)
                |serialNum;
    }
    private static long waitNextMillis(long timestamp) {
        long nowTimeStamp = System.currentTimeMillis();
        while(timestamp >= nowTimeStamp) {
            nowTimeStamp = System.currentTimeMillis();
        }
        return nowTimeStamp;
    }
}
